package com.eu.ebpm.engine.query;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import com.eu.ebpm.SpringContext;
import com.eu.ebpm.engine.cmd.Command;
import com.eu.ebpm.engine.entity.args.QueryParam;
import com.eu.ebpm.engine.exception.WorkFlowException;

/**
 * 
 * @author 王晓华
 * @param <T>
 *            查询接口
 * @param <U>
 *            目标值
 */
public abstract class AbstractQuery<T extends Query<?, ?>, U> implements Query<T, U> {
	
	// 命令
	protected Command<?> command;
	
	// 参数
	protected QueryParam arg = new QueryParam();

	protected String orderColumn;

	protected Map<String, String> orderColumnMap = null;

	@SuppressWarnings("unchecked")
	public T asc() {
		setOrder("ASC");
		return (T) this;
	}

	@SuppressWarnings("unchecked")
	public T desc() {
		setOrder("DESC");
		return (T) this;
	}

	private void setOrder(String type) {
		setOrder(orderColumn, type);
	}

	protected void setOrder(String column, String type) {
		if (orderColumnMap == null) {
			orderColumnMap = new LinkedHashMap<String, String>();
		}
		orderColumn = column;
		orderColumnMap.put(column, type);
	}

	protected void initOrderSql() {
		StringBuffer orderBySql = new StringBuffer("");
		if (orderColumnMap != null) {
			orderBySql.append(" ORDER BY ");
			for (String key : orderColumnMap.keySet()) {
				orderBySql.append(key).append(" ").append(orderColumnMap.get(key)).append(",");
			}
			orderBySql.deleteCharAt(orderBySql.length() - 1);
		}
		arg.setOrderBy(orderBySql.toString());
	}

	public U singleResult() {
		
		List<U> list = list();
		
		if (list.size() == 1) {
			return list.get(0);
		}
		
		if (list.size() > 1) {
			throw new WorkFlowException("查询结果列表数量期望是1,而实际是" + list.size());
		}
		
		return null;
	}

	@SuppressWarnings("unchecked")
	public List<U> list() {
		initOrderSql();
		return (List<U>) command.execute(arg);
	}

	@SuppressWarnings("unchecked")
	public Page<U> listPage(int currentPage, int pageSize) {
		initOrderSql();
		arg.setPageNum(currentPage);
		arg.setPageSize(pageSize);
		return (Page<U>) command.execute(arg);
	}

	/**
	 * 设置查询命令
	 * 
	 * @param name
	 *            命令标志
	 */
	public void setExecuteCommand(Class<?> clazz) {
		this.command = (Command<?>) SpringContext.getBean(clazz);
	}

}
